package vh.sphynx.net.core;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import vh.sphynx.net.ICacheManager;
import vh.sphynx.net.IUrlCacheResolver;

public class CacheManager implements ICacheManager {

	protected List<IUrlCacheResolver> resolvers = new ArrayList<IUrlCacheResolver>();
	private int expiredPeriod;
	private String archive;
	private String cacheFolder;
	
	protected static SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-hhmmss");
	
	public CacheManager(String cacheFolder, String archiveFolder) {
		this.archive = archiveFolder != null ? new File(archiveFolder).getAbsolutePath() : null;
		this.setCacheFolder(new File(cacheFolder).getAbsolutePath());
		File cf = new File(cacheFolder);
		if (!cf.exists())
			cf.mkdirs();
			
	}
	
	@Override
	public void addCacheNameResolver(IUrlCacheResolver resolver) {
		resolvers.add(resolver);
	}

	@Override
	public void removeCacheNameResolver(IUrlCacheResolver resovler) {
		resolvers.remove(resovler);
	}

	@Override
	public String resolveCacheName(URL query) {
		String name = null;
		for (int i = resolvers.size() - 1; i >= 0 && name == null; i--)
			name = resolvers.get(i).resolveCacheName(query);
		if (name == null)
			name = UrlCacheResolver.DEFAULT.resolveCacheName(query);
		return cacheFolder + "/" + name;
	}

	@Override
	public void archiveCache(URL query, String cacheFile) {
		if (archive == null) return;
		FileInputStream istream = null;
		ZipOutputStream out = null;
		try {
			File ad = new File(archive);
			if (!ad.exists())
				ad.mkdirs();
			
			File cf = new File(cacheFile);
			
			if (!cf.exists()) return;
			
			String name = archive + "/" + cf.getName() + "." + sdf.format(new Date(cf.lastModified())) + ".zip";
			out = new ZipOutputStream(new FileOutputStream(name, true));
			
			out.putNextEntry(new ZipEntry(cf.getName()));
			
			istream = new FileInputStream(cacheFile);
			byte[] buf = new byte[4096];
			int len;
			while ((len = istream.read(buf)) > 0)
				out.write(buf, 0, len);
			
			out.closeEntry();
			out.close();
			istream.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public int getCacheExpiredPeriod() {
		return this.expiredPeriod;
	}

	@Override
	public void setCacheExpiredPeriod(int secInterval) {
		this.expiredPeriod = secInterval;	
	}

	@Override
	public boolean isExpired(String cacheFile, long expiredTime) {
		File f = new File(cacheFile);
		if (expiredTime < 0)
			expiredTime = getCacheExpiredPeriod();
		Date expiredDate = new Date(f.lastModified() + expiredTime * 1000);
		Date today = new Date();
		return expiredDate.before(today);
	}

	public void setCacheFolder(String cacheFolder) {
		this.cacheFolder = cacheFolder;
	}

	public String getCacheFolder() {
		return cacheFolder;
	}

}
